import 'package:flutter/material.dart';
import 'package:stop_watch_timer/stop_watch_timer.dart';
import 'package:timer_count_down/timer_count_down.dart';

class WatchTimer extends StatefulWidget {
  const WatchTimer({Key key}) : super(key: key);

  @override
  _WatchTimerState createState() => _WatchTimerState();
}

class _WatchTimerState extends State<WatchTimer>
    with SingleTickerProviderStateMixin {
  final _isHours = true;
  // AnimationController _controller;
  bool _up = true;
  final _scrollController = ScrollController();
  final StopWatchTimer _stopWatchTimerUp = StopWatchTimer(
    mode: StopWatchMode.countUp,
    onChange: (value) => print('onChange $value'),
    onChangeRawSecond: (value) => print('onChangeRawSecond $value'),
    onChangeRawMinute: (value) => print('onChangeRawMinute $value'),
  );

  final StopWatchTimer _stopWatchTimerDown = StopWatchTimer(
    mode: StopWatchMode.countDown,
    presetMillisecond: StopWatchTimer.getMilliSecFromSecond(3),
    onChange: (value) => print('onChange $value'),
    onChangeRawSecond: (value) => print('onChangeRawSecond $value'),
    onChangeRawMinute: (value) => print('onChangeRawMinute $value'),
    onEnded: () {
      print('onEnded');
    },
  );

  @override
  void initState() {
    super.initState();
    // _controller = AnimationController(vsync: this);
    _stopWatchTimerUp.rawTime.listen((value) =>
        print('rawTime $value ${StopWatchTimer.getDisplayTime(value)}'));
    _stopWatchTimerUp.minuteTime.listen((value) => print('minuteTime $value'));
    _stopWatchTimerUp.secondTime.listen((value) => print('secondTime $value'));
    _stopWatchTimerUp.records.listen((value) => print('records $value'));

    /// Can be set preset time. This case is "00:01.23".
    // _stopWatchTimerUp.setPresetTime(mSec: 1234);

     _stopWatchTimerDown.rawTime.listen((value) =>
        print('rawTime $value ${StopWatchTimer.getDisplayTime(value)}'));
    _stopWatchTimerDown.minuteTime.listen((value) => print('minuteTime $value'));
    _stopWatchTimerDown.secondTime.listen((value) => print('secondTime $value'));
    _stopWatchTimerDown.records.listen((value) => print('records $value'));

    /// Can be set preset time. This case is "00:01.23".
    // _stopWatchTimerDown.setPresetTime(mSec: 1234);
  }

  @override
  void dispose() async {
    super.dispose();
    // _controller.dispose();
    await _stopWatchTimerUp.dispose();
    await _stopWatchTimerDown.dispose();
    print('dispose Finish');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('倒计时'),
      ),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 4),
            child: ElevatedButton(
              style: ElevatedButton.styleFrom(
                primary: Colors.pinkAccent,
                padding: const EdgeInsets.all(4),
                shape: const StadiumBorder(),
              ),
              onPressed: () {
                setState(() {
                  _up = !_up;
                });
              },
              child: Padding(
                padding: EdgeInsets.symmetric(horizontal: 16),
                child: Text(
                  _up ? 'CountUpTimer' : 'CountDownTimer',
                  style: TextStyle(color: Colors.white),
                ),
              ),
            ),
          ),
          _up?uptimer():downTimer()
        ],
      ),
    );
  }

  Widget eg() {
    return Countdown(
      seconds: 10000,
      build: (BuildContext context, double time) => Text(time.toString()),
      interval: Duration(milliseconds: 100),
      onFinished: () {
        print('Timer is done!');
      },
    );
  }

  Widget uptimer() {
    return Column(children: [
      /// Display stop watch time
      Padding(
        padding: const EdgeInsets.only(bottom: 0),
        child: StreamBuilder<int>(
          stream: _stopWatchTimerUp.rawTime,
          initialData: _stopWatchTimerUp.rawTime.value,
          builder: (context, snap) {
            final value = snap.data;
            final displayTime =
                StopWatchTimer.getDisplayTime(value, hours: _isHours);
            return Column(
              children: <Widget>[
                Padding(
                  padding: const EdgeInsets.all(8),
                  child: Text(
                    displayTime,
                    style: const TextStyle(
                        fontSize: 40,
                        fontFamily: 'Helvetica',
                        fontWeight: FontWeight.bold),
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.all(8),
                  child: Text(
                    value.toString(),
                    style: const TextStyle(
                        fontSize: 16,
                        fontFamily: 'Helvetica',
                        fontWeight: FontWeight.w400),
                  ),
                ),
              ],
            );
          },
        ),
      ),

      /// Display every minute.
      Padding(
        padding: const EdgeInsets.only(bottom: 0),
        child: StreamBuilder<int>(
          stream: _stopWatchTimerUp.minuteTime,
          initialData: _stopWatchTimerUp.minuteTime.value,
          builder: (context, snap) {
            final value = snap.data;
            print('Listen every minute. $value');
            return Column(
              children: <Widget>[
                Padding(
                    padding: const EdgeInsets.all(8),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: <Widget>[
                        const Padding(
                          padding: EdgeInsets.symmetric(horizontal: 4),
                          child: Text(
                            'minute',
                            style: TextStyle(
                              fontSize: 17,
                              fontFamily: 'Helvetica',
                            ),
                          ),
                        ),
                        Padding(
                          padding: const EdgeInsets.symmetric(horizontal: 4),
                          child: Text(
                            value.toString(),
                            style: const TextStyle(
                                fontSize: 30,
                                fontFamily: 'Helvetica',
                                fontWeight: FontWeight.bold),
                          ),
                        ),
                      ],
                    )),
              ],
            );
          },
        ),
      ),

      /// Display every second.
      Padding(
        padding: const EdgeInsets.only(bottom: 0),
        child: StreamBuilder<int>(
          stream: _stopWatchTimerUp.secondTime,
          initialData: _stopWatchTimerUp.secondTime.value,
          builder: (context, snap) {
            final value = snap.data;
            print('Listen every second. $value');
            return Column(
              children: <Widget>[
                Padding(
                    padding: const EdgeInsets.all(8),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: <Widget>[
                        const Padding(
                          padding: EdgeInsets.symmetric(horizontal: 4),
                          child: Text(
                            'second',
                            style: TextStyle(
                              fontSize: 17,
                              fontFamily: 'Helvetica',
                            ),
                          ),
                        ),
                        Padding(
                          padding: const EdgeInsets.symmetric(horizontal: 4),
                          child: Text(
                            value.toString(),
                            style: const TextStyle(
                              fontSize: 30,
                              fontFamily: 'Helvetica',
                              fontWeight: FontWeight.bold,
                            ),
                          ),
                        ),
                      ],
                    )),
              ],
            );
          },
        ),
      ),

      /// Lap time.
      Container(
        height: 120,
        margin: const EdgeInsets.all(8),
        child: StreamBuilder<List<StopWatchRecord>>(
          stream: _stopWatchTimerUp.records,
          initialData: _stopWatchTimerUp.records.value,
          builder: (context, snap) {
            final value = snap.data;
            if (value.isEmpty) {
              return Container();
            }
            Future.delayed(const Duration(milliseconds: 100), () {
              _scrollController.animateTo(
                  _scrollController.position.maxScrollExtent,
                  duration: const Duration(milliseconds: 200),
                  curve: Curves.easeOut);
            });
            print('Listen records. $value');
            return ListView.builder(
              controller: _scrollController,
              scrollDirection: Axis.vertical,
              itemBuilder: (BuildContext context, int index) {
                final data = value[index];
                return Column(
                  children: <Widget>[
                    Padding(
                      padding: const EdgeInsets.all(8),
                      child: Text(
                        '${index + 1} ${data.displayTime}',
                        style: const TextStyle(
                            fontSize: 17,
                            fontFamily: 'Helvetica',
                            fontWeight: FontWeight.bold),
                      ),
                    ),
                    const Divider(
                      height: 1,
                    )
                  ],
                );
              },
              itemCount: value.length,
            );
          },
        ),
      ),

      /// Button
      Padding(
        padding: const EdgeInsets.all(2),
        child: Column(
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.only(bottom: 0),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Padding(
                    padding: const EdgeInsets.symmetric(horizontal: 4),
                    child: RaisedButton(
                      padding: const EdgeInsets.all(4),
                      color: Colors.lightBlue,
                      shape: const StadiumBorder(),
                      onPressed: () async {
                        _stopWatchTimerUp.onExecute.add(StopWatchExecute.start);
                      },
                      child: const Text(
                        'Start',
                        style: TextStyle(color: Colors.white),
                      ),
                    ),
                  ),
                  Padding(
                    padding: const EdgeInsets.symmetric(horizontal: 4),
                    child: RaisedButton(
                      padding: const EdgeInsets.all(4),
                      color: Colors.green,
                      shape: const StadiumBorder(),
                      onPressed: () async {
                        _stopWatchTimerUp.onExecute.add(StopWatchExecute.stop);
                      },
                      child: const Text(
                        'Stop',
                        style: TextStyle(color: Colors.white),
                      ),
                    ),
                  ),
                  Padding(
                    padding: const EdgeInsets.symmetric(horizontal: 4),
                    child: RaisedButton(
                      padding: const EdgeInsets.all(4),
                      color: Colors.red,
                      shape: const StadiumBorder(),
                      onPressed: () async {
                        _stopWatchTimerUp.onExecute.add(StopWatchExecute.reset);
                      },
                      child: const Text(
                        'Reset',
                        style: TextStyle(color: Colors.white),
                      ),
                    ),
                  ),
                ],
              ),
            ),
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 4),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Padding(
                    padding: const EdgeInsets.all(0).copyWith(right: 8),
                    child: RaisedButton(
                      padding: const EdgeInsets.all(4),
                      color: Colors.deepPurpleAccent,
                      shape: const StadiumBorder(),
                      onPressed: () async {
                        _stopWatchTimerUp.onExecute.add(StopWatchExecute.lap);
                      },
                      child: const Text(
                        'Lap',
                        style: TextStyle(color: Colors.white),
                      ),
                    ),
                  ),
                ],
              ),
            ),
            Padding(
              padding: const EdgeInsets.all(0),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Padding(
                    padding: const EdgeInsets.symmetric(horizontal: 4),
                    child: RaisedButton(
                      padding: const EdgeInsets.all(4),
                      color: Colors.pinkAccent,
                      shape: const StadiumBorder(),
                      onPressed: () async {
                        _stopWatchTimerUp.setPresetHoursTime(1);
                      },
                      child: const Text(
                        'Set Hours',
                        style: TextStyle(color: Colors.white),
                      ),
                    ),
                  ),
                  Padding(
                    padding: const EdgeInsets.symmetric(horizontal: 4),
                    child: RaisedButton(
                      padding: const EdgeInsets.all(4),
                      color: Colors.pinkAccent,
                      shape: const StadiumBorder(),
                      onPressed: () async {
                        _stopWatchTimerUp.setPresetMinuteTime(59);
                      },
                      child: const Text(
                        'Set Minute',
                        style: TextStyle(color: Colors.white),
                      ),
                    ),
                  ),
                  Padding(
                    padding: const EdgeInsets.symmetric(horizontal: 4),
                    child: RaisedButton(
                      padding: const EdgeInsets.all(4),
                      color: Colors.pinkAccent,
                      shape: const StadiumBorder(),
                      onPressed: () async {
                        _stopWatchTimerUp.setPresetSecondTime(10);
                      },
                      child: const Text(
                        'Set Second',
                        style: TextStyle(color: Colors.white),
                      ),
                    ),
                  ),
                ],
              ),
            ),
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 4),
              child: RaisedButton(
                padding: const EdgeInsets.all(4),
                color: Colors.pinkAccent,
                shape: const StadiumBorder(),
                onPressed: () async {
                  _stopWatchTimerUp.setPresetTime(mSec: 3599 * 1000);
                },
                child: const Text(
                  'Set PresetTime',
                  style: TextStyle(color: Colors.white),
                ),
              ),
            ),
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 4),
              child: ElevatedButton(
                style: ElevatedButton.styleFrom(
                  primary: Colors.pinkAccent,
                  onPrimary: Colors.white,
                  shape: const StadiumBorder(),
                ),
                onPressed: () async {
                  _stopWatchTimerUp.clearPresetTime();
                },
                child: const Text(
                  'Clear PresetTime',
                  style: TextStyle(color: Colors.white),
                ),
              ),
            ),
          ],
        ),
      ),
    ]);
  }

  Widget downTimer(){
    return Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            /// Display stop watch time
            Padding(
              padding: const EdgeInsets.only(bottom: 0),
              child: StreamBuilder<int>(
                stream: _stopWatchTimerDown.rawTime,
                initialData: _stopWatchTimerDown.rawTime.value,
                builder: (context, snap) {
                  final value = snap.data;
                  final displayTime =
                      StopWatchTimer.getDisplayTime(value, hours: _isHours);
                  return Column(
                    children: <Widget>[
                      Padding(
                        padding: const EdgeInsets.all(8),
                        child: Text(
                          displayTime,
                          style: const TextStyle(
                              fontSize: 40,
                              fontFamily: 'Helvetica',
                              fontWeight: FontWeight.bold),
                        ),
                      ),
                      Padding(
                        padding: const EdgeInsets.all(8),
                        child: Text(
                          value.toString(),
                          style: const TextStyle(
                              fontSize: 16,
                              fontFamily: 'Helvetica',
                              fontWeight: FontWeight.w400),
                        ),
                      ),
                    ],
                  );
                },
              ),
            ),

            /// Display every minute.
            Padding(
              padding: const EdgeInsets.only(bottom: 0),
              child: StreamBuilder<int>(
                stream: _stopWatchTimerDown.minuteTime,
                initialData: _stopWatchTimerDown.minuteTime.value,
                builder: (context, snap) {
                  final value = snap.data;
                  print('Listen every minute. $value');
                  return Column(
                    children: <Widget>[
                      Padding(
                          padding: const EdgeInsets.all(8),
                          child: Row(
                            mainAxisAlignment: MainAxisAlignment.center,
                            crossAxisAlignment: CrossAxisAlignment.center,
                            children: <Widget>[
                              const Padding(
                                padding: EdgeInsets.symmetric(horizontal: 4),
                                child: Text(
                                  'minute',
                                  style: TextStyle(
                                    fontSize: 17,
                                    fontFamily: 'Helvetica',
                                  ),
                                ),
                              ),
                              Padding(
                                padding:
                                    const EdgeInsets.symmetric(horizontal: 4),
                                child: Text(
                                  value.toString(),
                                  style: const TextStyle(
                                      fontSize: 30,
                                      fontFamily: 'Helvetica',
                                      fontWeight: FontWeight.bold),
                                ),
                              ),
                            ],
                          )),
                    ],
                  );
                },
              ),
            ),

            /// Display every second.
            Padding(
              padding: const EdgeInsets.only(bottom: 0),
              child: StreamBuilder<int>(
                stream: _stopWatchTimerDown.secondTime,
                initialData: _stopWatchTimerDown.secondTime.value,
                builder: (context, snap) {
                  final value = snap.data;
                  print('Listen every second. $value');
                  return Column(
                    children: <Widget>[
                      Padding(
                          padding: const EdgeInsets.all(8),
                          child: Row(
                            mainAxisAlignment: MainAxisAlignment.center,
                            crossAxisAlignment: CrossAxisAlignment.center,
                            children: <Widget>[
                              const Padding(
                                padding: EdgeInsets.symmetric(horizontal: 4),
                                child: Text(
                                  'second',
                                  style: TextStyle(
                                    fontSize: 17,
                                    fontFamily: 'Helvetica',
                                  ),
                                ),
                              ),
                              Padding(
                                padding:
                                    const EdgeInsets.symmetric(horizontal: 4),
                                child: Text(
                                  value.toString(),
                                  style: const TextStyle(
                                    fontSize: 30,
                                    fontFamily: 'Helvetica',
                                    fontWeight: FontWeight.bold,
                                  ),
                                ),
                              ),
                            ],
                          )),
                    ],
                  );
                },
              ),
            ),

            /// Lap time.
            Container(
              height: 120,
              margin: const EdgeInsets.all(8),
              child: StreamBuilder<List<StopWatchRecord>>(
                stream: _stopWatchTimerDown.records,
                initialData: _stopWatchTimerDown.records.value,
                builder: (context, snap) {
                  final value = snap.data;
                  if (value.isEmpty) {
                    return Container();
                  }
                  Future.delayed(const Duration(milliseconds: 100), () {
                    _scrollController.animateTo(
                        _scrollController.position.maxScrollExtent,
                        duration: const Duration(milliseconds: 200),
                        curve: Curves.easeOut);
                  });
                  print('Listen records. $value');
                  return ListView.builder(
                    controller: _scrollController,
                    scrollDirection: Axis.vertical,
                    itemBuilder: (BuildContext context, int index) {
                      final data = value[index];
                      return Column(
                        children: <Widget>[
                          Padding(
                            padding: const EdgeInsets.all(8),
                            child: Text(
                              '${index + 1} ${data.displayTime}',
                              style: const TextStyle(
                                  fontSize: 17,
                                  fontFamily: 'Helvetica',
                                  fontWeight: FontWeight.bold),
                            ),
                          ),
                          const Divider(
                            height: 1,
                          )
                        ],
                      );
                    },
                    itemCount: value.length,
                  );
                },
              ),
            ),

            /// Button
            Padding(
              padding: const EdgeInsets.all(2),
              child: Column(
                children: <Widget>[
                  Padding(
                    padding: const EdgeInsets.only(bottom: 0),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        Padding(
                          padding: const EdgeInsets.symmetric(horizontal: 4),
                          child: ElevatedButton(
                            style: ElevatedButton.styleFrom(
                              primary: Colors.lightBlue,
                              onPrimary: Colors.white,
                              shape: const StadiumBorder(),
                            ),
                            onPressed: () async {
                              _stopWatchTimerDown.onExecute
                                  .add(StopWatchExecute.start);
                            },
                            child: const Text(
                              'Start',
                              style: TextStyle(color: Colors.white),
                            ),
                          ),
                        ),
                        Padding(
                          padding: const EdgeInsets.symmetric(horizontal: 4),
                          child: ElevatedButton(
                            style: ElevatedButton.styleFrom(
                              primary: Colors.green,
                              onPrimary: Colors.white,
                              shape: const StadiumBorder(),
                            ),
                            onPressed: () async {
                              _stopWatchTimerDown.onExecute
                                  .add(StopWatchExecute.stop);
                            },
                            child: const Text(
                              'Stop',
                              style: TextStyle(color: Colors.white),
                            ),
                          ),
                        ),
                        Padding(
                          padding: const EdgeInsets.symmetric(horizontal: 4),
                          child: ElevatedButton(
                            style: ElevatedButton.styleFrom(
                              primary: Colors.red,
                              onPrimary: Colors.white,
                              shape: const StadiumBorder(),
                            ),
                            onPressed: () async {
                              _stopWatchTimerDown.onExecute
                                  .add(StopWatchExecute.reset);
                            },
                            child: const Text(
                              'Reset',
                              style: TextStyle(color: Colors.white),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                  Padding(
                    padding: const EdgeInsets.symmetric(horizontal: 4),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        Padding(
                          padding: const EdgeInsets.all(0).copyWith(right: 8),
                          child: ElevatedButton(
                            style: ElevatedButton.styleFrom(
                              primary: Colors.deepPurpleAccent,
                              onPrimary: Colors.white,
                              shape: const StadiumBorder(),
                            ),
                            onPressed: () async {
                              _stopWatchTimerDown.onExecute
                                  .add(StopWatchExecute.lap);
                            },
                            child: const Text(
                              'Lap',
                              style: TextStyle(color: Colors.white),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                  Padding(
                    padding: const EdgeInsets.all(0),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        Padding(
                          padding: const EdgeInsets.symmetric(horizontal: 4),
                          child: ElevatedButton(
                            style: ElevatedButton.styleFrom(
                              primary: Colors.pinkAccent,
                              onPrimary: Colors.white,
                              shape: const StadiumBorder(),
                            ),
                            onPressed: () async {
                              _stopWatchTimerDown.setPresetHoursTime(1);
                            },
                            child: const Text(
                              'Set Hours',
                              style: TextStyle(color: Colors.white),
                            ),
                          ),
                        ),
                        Padding(
                          padding: const EdgeInsets.symmetric(horizontal: 4),
                          child: ElevatedButton(
                            style: ElevatedButton.styleFrom(
                              primary: Colors.pinkAccent,
                              onPrimary: Colors.white,
                              shape: const StadiumBorder(),
                            ),
                            onPressed: () async {
                              _stopWatchTimerDown.setPresetMinuteTime(59);
                            },
                            child: const Text(
                              'Set Minute',
                              style: TextStyle(color: Colors.white),
                            ),
                          ),
                        ),
                        Padding(
                          padding: const EdgeInsets.symmetric(horizontal: 4),
                          child: ElevatedButton(
                            style: ElevatedButton.styleFrom(
                              primary: Colors.pinkAccent,
                              onPrimary: Colors.white,
                              shape: const StadiumBorder(),
                            ),
                            onPressed: () async {
                              _stopWatchTimerDown.setPresetSecondTime(10);
                            },
                            child: const Text(
                              'Set Second',
                              style: TextStyle(color: Colors.white),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                  Padding(
                    padding: const EdgeInsets.symmetric(horizontal: 4),
                    child: ElevatedButton(
                      style: ElevatedButton.styleFrom(
                        primary: Colors.pinkAccent,
                        onPrimary: Colors.white,
                        shape: const StadiumBorder(),
                      ),
                      onPressed: () async {
                        _stopWatchTimerDown.setPresetTime(mSec: 3599 * 1000);
                      },
                      child: const Text(
                        'Set PresetTime',
                        style: TextStyle(color: Colors.white),
                      ),
                    ),
                  ),
                  Padding(
                    padding: const EdgeInsets.symmetric(horizontal: 4),
                    child: ElevatedButton(
                      style: ElevatedButton.styleFrom(
                        primary: Colors.pinkAccent,
                        onPrimary: Colors.white,
                        shape: const StadiumBorder(),
                      ),
                      onPressed: () async {
                        _stopWatchTimerDown.clearPresetTime();
                      },
                      child: const Text(
                        'Clear PresetTime',
                        style: TextStyle(color: Colors.white),
                      ),
                    ),
                  ),
                ],
              ),
            )
          ],
        );
  }
}
